#[cfg(test)]
mod tests {
    use crate::{converter::Converter, config::Config};
    use std::fs;
    use std::path::PathBuf;
    use std::sync::{Mutex, OnceLock};
    use tempfile::TempDir;

    static WORKDIR_LOCK: OnceLock<Mutex<()>> = OnceLock::new();

    fn create_test_vcxproj() -> String {
        r#"<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <AdditionalIncludeDirectories>includes;includes/spdlog;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <LanguageStandard>stdcpp17</LanguageStandard>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>Mv3dLp.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <VCProjectVersion>16.0</VCProjectVersion>
    <ProjectGuid>{12345678-1234-1234-1234-123456789012}</ProjectGuid>
    <RootNamespace>TestProject</RootNamespace>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
  </PropertyGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp" />
    <ClCompile Include="utils.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="utils.h" />
  </ItemGroup>
</Project>"#.to_string()
    }

    fn create_test_sln() -> String {
        r#"Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30320.27
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestProject", "TestProject\TestProject.vcxproj", "{12345678-1234-1234-1234-123456789012}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|x64 = Debug|x64
        Release|x64 = Release|x64
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {12345678-1234-1234-1234-123456789012}.Debug|x64.ActiveCfg = Debug|Win32
        {12345678-1234-1234-1234-123456789012}.Release|x64.ActiveCfg = Release|Win32
    EndGlobalSection
EndGlobal"#.to_string()
    }

    #[test]
    fn test_converter_integration() {
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("TestProject.vcxproj");
        
        // 创建测试项目文件
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();
        
        // 测试转换
        let converter = Converter::new();
        let config = Config::default();
        let result = converter.convert(&vcxproj_path, "xmake", temp_dir.path(), &config);
        
        assert!(result.is_ok(), "Conversion should succeed: {:?}", result);
        let generated_file = temp_dir.path().join("xmake.lua");
        assert!(generated_file.exists(), "Output file should be created");
        
        // 检查生成的内容
        let content = fs::read_to_string(&generated_file).unwrap();
        assert!(content.contains("target(\"TestProject\")"));
        assert!(content.contains("main.cpp"));
        assert!(content.contains("utils.cpp"));
    }

    #[test]
    fn test_solution_parsing() {
        let temp_dir = TempDir::new().unwrap();
        let sln_path = temp_dir.path().join("TestSolution.sln");
        let vcxproj_dir = temp_dir.path().join("TestProject");
        let vcxproj_path = vcxproj_dir.join("TestProject.vcxproj");
        
        // 创建目录结构
        fs::create_dir_all(&vcxproj_dir).unwrap();
        fs::write(&sln_path, create_test_sln()).unwrap();
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();
        
        let converter = Converter::new();
        let config = Config::default();
        let result = converter.convert(&sln_path, "xmake", temp_dir.path(), &config);
        
        assert!(result.is_ok(), "Solution conversion should succeed: {:?}", result);
    }

    #[test]
    fn test_config_file_operations() {
        let temp_dir = TempDir::new().unwrap();
        
        let config_path = temp_dir.path().join("config.toml");

        let config = Config {
            input_path: PathBuf::from("test.sln"),
            generator: "xmake".to_string(),
            log_level: "debug".to_string(),
            project_root: None,
            environment_variables: crate::config::EnvironmentVariablesConfig::default(),
            pre_migration_scripts: crate::config::PreMigrationScripts::default(),
            code_style: crate::config::CodeStyleConfig::default(),
        };

        // 写入 TOML 配置
        let result = config.to_file(&config_path);
        assert!(result.is_ok(), "TOML config write should succeed: {:?}", result);
        assert!(config_path.exists());

        // 读取 TOML 配置
        let loaded_config = Config::from_file(&config_path);
        assert!(loaded_config.is_ok(), "TOML config read should succeed: {:?}", loaded_config);

        let loaded = loaded_config.unwrap();
        assert_eq!(loaded.generator, "xmake");
        assert_eq!(loaded.log_level, "debug");
    }

    #[test]
    fn test_error_handling() {
        let converter = Converter::new();
        
        // 测试不存在的文件
        let temp_dir_for_root = TempDir::new().unwrap();
        let config = Config::default();
        let result = converter.convert(
            &PathBuf::from("nonexistent.vcxproj"),
            "xmake",
            temp_dir_for_root.path(),
            &config
        );
        assert!(result.is_err());
        
        // 测试不支持的生成器
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("test.vcxproj");
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();
        
        let result = converter.convert(&vcxproj_path, "unsupported", temp_dir.path(), &config);
        assert!(result.is_err());
        
        if let Err(e) = result {
            assert!(matches!(e, crate::BuildMigrateError::Generator(_)));
        }
    }

    // ============== Qt 相关测试用例 ==============

    fn create_qt_vcxproj_basic() -> String {
        r#"<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{F77EE7CB-933D-404C-9939-3E2E8C9D1006}</ProjectGuid>
    <Keyword>QtVS_v304</Keyword>
    <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
    <QtInstall>5.12.5_x64</QtInstall>
    <QtModules>core;gui;widgets</QtModules>
    <QtBuildConfig>debug</QtBuildConfig>
    <LanguageStandard>stdcpp17</LanguageStandard>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
    <QtInstall>5.12.5_x64</QtInstall>
    <QtModules>core;gui;widgets;network</QtModules>
    <QtBuildConfig>release</QtBuildConfig>
    <LanguageStandard>stdcpp17</LanguageStandard>
  </PropertyGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp" />
    <ClCompile Include="MainWindow.cpp" />
    <ClCompile Include="NetworkManager.cpp" />
  </ItemGroup>
  <ItemGroup>
    <QtMoc Include="MainWindow.h" />
    <QtMoc Include="NetworkManager.h" />
  </ItemGroup>
  <ItemGroup>
    <QtUic Include="MainWindow.ui" />
    <QtUic Include="SettingsDialog.ui" />
  </ItemGroup>
  <ItemGroup>
    <QtRcc Include="resources.qrc" />
  </ItemGroup>
</Project>"#.to_string()
    }

    fn create_qt_vcxproj_complex() -> String {
        r#"<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{ABCD1234-5678-9012-3456-789012345678}</ProjectGuid>
    <Keyword>QtVS_v304</Keyword>
    <QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
    <QtInstall>6.5.0_msvc2019_64</QtInstall>
    <QtModules>core;gui;widgets;network;sql;multimedia;concurrent</QtModules>
    <QtBuildConfig>debug</QtBuildConfig>
    <QtMocExe>$(QTDIR)\bin\moc.exe</QtMocExe>
    <QtUicExe>$(QTDIR)\bin\uic.exe</QtUicExe>
    <QtRccExe>$(QTDIR)\bin\rcc.exe</QtRccExe>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
    <QtInstall>6.5.0_msvc2019_64</QtInstall>
    <QtModules>core;gui;widgets;network;sql;multimedia;concurrent</QtModules>
    <QtBuildConfig>release</QtBuildConfig>
  </PropertyGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp" />
    <ClCompile Include="MainWindow.cpp" />
    <ClCompile Include="DatabaseManager.cpp" />
    <ClCompile Include="MediaPlayer.cpp" />
    <ClCompile Include="utils\Logger.cpp" />
    <ClCompile Include="widgets\CustomButton.cpp" />
  </ItemGroup>
  <ItemGroup>
    <QtMoc Include="MainWindow.h" />
    <QtMoc Include="DatabaseManager.h" />
    <QtMoc Include="MediaPlayer.h" />
    <QtMoc Include="widgets\CustomButton.h" />
  </ItemGroup>
  <ItemGroup>
    <QtUic Include="ui\MainWindow.ui" />
    <QtUic Include="ui\SettingsDialog.ui" />
    <QtUic Include="ui\AboutDialog.ui" />
  </ItemGroup>
  <ItemGroup>
    <QtRcc Include="resources\icons.qrc" />
    <QtRcc Include="resources\styles.qrc" />
    <QtRcc Include="resources\translations.qrc" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="utils\Constants.h" />
    <ClInclude Include="types\DataTypes.h" />
  </ItemGroup>
</Project>"#.to_string()
    }

    #[test]
    fn test_qt_basic_project_parsing() {
        use crate::parsers::{Parser, vs_parser::VsParser};
        
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("QtBasicProject.vcxproj");
        
        // 创建基础 Qt 项目文件
        fs::write(&vcxproj_path, create_qt_vcxproj_basic()).unwrap();
        
        let parser = VsParser::new();
        let result = parser.parse(&vcxproj_path);
        assert!(result.is_ok(), "Qt project parsing should succeed: {:?}", result);
        
        let solution = result.unwrap();
        assert_eq!(solution.projects.len(), 1);
        
        let project = &solution.projects[0];
        
        // 验证项目基本信息
        assert_eq!(project.name, "QtBasicProject");
        assert_eq!(project.source_files.len(), 3); // main.cpp, MainWindow.cpp, NetworkManager.cpp
        
        // 调试输出配置信息
        for (config_name, config) in &project.configurations {
            println!("Configuration: {:?}", config_name);
            println!("  Qt enabled: {}", config.qt_settings.enabled);
            println!("  Qt version: {:?}", config.qt_settings.version);
            println!("  Qt modules: {:?}", config.qt_settings.modules);
            println!("  Moc files count: {}", config.qt_settings.moc_files.len());
            println!("  UI files count: {}", config.qt_settings.ui_files.len());
            println!("  Resource files count: {}", config.qt_settings.resource_files.len());
        }
        
        // 验证 Debug 配置的 Qt 设置
        let debug_config = project.configurations.get(&crate::core::BuildConfiguration::Debug).unwrap();
        assert!(debug_config.qt_settings.enabled);
        assert_eq!(debug_config.qt_settings.version.as_ref().unwrap(), "5.12.5");
        assert_eq!(debug_config.qt_settings.modules, vec!["core", "gui", "widgets"]);
        assert_eq!(debug_config.qt_settings.moc_files.len(), 2); // MainWindow.h, NetworkManager.h
        assert_eq!(debug_config.qt_settings.ui_files.len(), 2); // MainWindow.ui, SettingsDialog.ui
        assert_eq!(debug_config.qt_settings.resource_files.len(), 1); // resources.qrc
        
        // 验证 Release 配置的 Qt 设置
        let release_config = project.configurations.get(&crate::core::BuildConfiguration::Release).unwrap();
        assert!(release_config.qt_settings.enabled);
        assert_eq!(release_config.qt_settings.version.as_ref().unwrap(), "5.12.5");
        assert_eq!(release_config.qt_settings.modules, vec!["core", "gui", "widgets", "network"]);
    }

    #[test]
    fn test_qt_complex_project_parsing() {
        use crate::parsers::{Parser, vs_parser::VsParser};
        
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("QtComplexProject.vcxproj");
        
        // 创建复杂 Qt 项目文件
        fs::write(&vcxproj_path, create_qt_vcxproj_complex()).unwrap();
        
        let parser = VsParser::new();
        let result = parser.parse(&vcxproj_path);
        assert!(result.is_ok(), "Complex Qt project parsing should succeed: {:?}", result);
        
        let solution = result.unwrap();
        let project = &solution.projects[0];
        
        // 验证复杂项目的结构
        assert_eq!(project.source_files.len(), 6); // 6个 cpp 文件
        
        let debug_config = project.configurations.get(&crate::core::BuildConfiguration::Debug).unwrap();
        
        // 验证 Qt 6.5.0 版本解析
        assert_eq!(debug_config.qt_settings.version.as_ref().unwrap(), "6.5.0");
        
        // 验证多个 Qt 模块
        let expected_modules = vec!["core", "gui", "widgets", "network", "sql", "multimedia", "concurrent"];
        assert_eq!(debug_config.qt_settings.modules, expected_modules);
        
        // 验证 moc 文件数量（4个头文件）
        assert_eq!(debug_config.qt_settings.moc_files.len(), 4);
        
        // 验证 ui 文件数量（3个 ui 文件）
        assert_eq!(debug_config.qt_settings.ui_files.len(), 3);
        
        // 验证资源文件数量（3个 qrc 文件）
        assert_eq!(debug_config.qt_settings.resource_files.len(), 3);
        
        // 验证 Qt 工具路径配置
        assert!(debug_config.qt_settings.tools.moc_exe.is_some());
        assert!(debug_config.qt_settings.tools.uic_exe.is_some());
        assert!(debug_config.qt_settings.tools.rcc_exe.is_some());
    }

    #[test]
    fn test_qt_version_parsing() {
        use crate::parsers::vs_parser::VsParser;
        
        let parser = VsParser::new();
        
        // 测试各种 Qt 版本格式
        assert_eq!(parser.parse_qt_install("5.12.5_x64"), Some("5.12.5".to_string()));
        assert_eq!(parser.parse_qt_install("6.5.0_msvc2019_64"), Some("6.5.0".to_string()));
        assert_eq!(parser.parse_qt_install("5.15.2_mingw81_64"), Some("5.15.2".to_string()));
        assert_eq!(parser.parse_qt_install("6.2.0"), Some("6.2.0".to_string()));
        assert_eq!(parser.parse_qt_install("5.9.8_msvc2017_32"), Some("5.9.8".to_string()));
        
        // 测试无效格式
        assert_eq!(parser.parse_qt_install("invalid_format"), None);
        assert_eq!(parser.parse_qt_install(""), None);
        assert_eq!(parser.parse_qt_install("x64_only"), None);
    }

    #[test]
    fn test_language_standard_debug() {
        use crate::parsers::{Parser, vs_parser::VsParser};
        
        // 初始化日志记录器
        let _ = env_logger::try_init();
        
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("TestProject.vcxproj");
        
        // 创建测试项目文件，包含 ItemDefinitionGroup 中的 LanguageStandard
        let test_content = create_test_vcxproj();
        println!("Test vcxproj content:\n{}", test_content);
        fs::write(&vcxproj_path, test_content).unwrap();
        
        // 使用解析器直接解析项目
        let parser = VsParser::new();
        let solution = parser.parse(&vcxproj_path).unwrap();
        let project = &solution.projects[0];
        
        println!("Project configurations found: {}", project.configurations.len());
        for (config, settings) in &project.configurations {
            println!("Configuration: {:?}", config);
            println!("  Language standard: {:?}", settings.language_standard);
            println!("  Qt enabled: {}", settings.qt_settings.enabled);
        }
        
        // 验证是否有任何配置包含语言标准
        let has_language_standard = project.configurations.values()
            .any(|settings| settings.language_standard.is_some());
        
        assert!(has_language_standard, "At least one configuration should have language standard set");
    }

    #[test]
    fn test_qt_project_conversion_to_xmake() {
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("QtTestProject.vcxproj");
        
        // 创建 Qt 项目文件
        fs::write(&vcxproj_path, create_qt_vcxproj_basic()).unwrap();
        
        // 执行转换
        let converter = Converter::new();
        let config = Config::default();
        let result = converter.convert(&vcxproj_path, "xmake", temp_dir.path(), &config);
        assert!(result.is_ok(), "Qt project conversion should succeed: {:?}", result);
        let output_path = temp_dir.path().join("xmake.lua");
        assert!(output_path.exists(), "Output xmake.lua should be created");
        
        // 验证生成的 xmake.lua 内容
        let content = fs::read_to_string(&output_path).unwrap();
        
        // 检查基本项目结构
        assert!(content.contains("target(\"QtTestProject\")"));
        assert!(content.contains("set_kind(\"binary\")"));
        
        // 检查 Qt 框架配置 - 检查实际的 Qt 模块配置
        assert!(content.contains("add_frameworks("));
        assert!(content.contains("add_rules(\"qt.widgetapp\")"));
        
        // 检查语言标准设置
        assert!(content.contains("set_languages(\"c++17\")"));
        
        // 检查 Qt 模块配置 - 修正期望值，xmake生成的是QtCore而不是qt.core
        assert!(content.contains("QtCore"));
        assert!(content.contains("QtGui"));  
        assert!(content.contains("QtWidgets"));
        
        // 检查源文件
        assert!(content.contains("main.cpp"));
        assert!(content.contains("MainWindow.cpp"));
        assert!(content.contains("NetworkManager.cpp"));
        
        // 检查 moc 文件处理
        assert!(content.contains("MainWindow.h"));
        assert!(content.contains("NetworkManager.h"));
        
        // 检查 UI 文件处理
        assert!(content.contains("MainWindow.ui"));
        assert!(content.contains("SettingsDialog.ui"));
        
        // 检查资源文件处理
        assert!(content.contains("resources.qrc"));
    }

    #[test]
    fn test_qt_configuration_specific_modules() {
        use crate::parsers::{Parser, vs_parser::VsParser};
        
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("QtConfigTest.vcxproj");
        
        // 创建项目文件
        fs::write(&vcxproj_path, create_qt_vcxproj_basic()).unwrap();
        
        let parser = VsParser::new();
        let solution = parser.parse(&vcxproj_path).unwrap();
        let project = &solution.projects[0];
        
        // 验证 Debug 配置只有基础模块
        let debug_config = project.configurations.get(&crate::core::BuildConfiguration::Debug).unwrap();
        assert_eq!(debug_config.qt_settings.modules.len(), 3);
        assert!(!debug_config.qt_settings.modules.contains(&"network".to_string()));
        
        // 验证 Release 配置包含网络模块
        let release_config = project.configurations.get(&crate::core::BuildConfiguration::Release).unwrap();
        assert_eq!(release_config.qt_settings.modules.len(), 4);
        assert!(release_config.qt_settings.modules.contains(&"network".to_string()));
    }

    #[test]
    fn test_qt_file_path_resolution() {
        use crate::parsers::{Parser, vs_parser::VsParser};
        
        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("QtPathTest.vcxproj");
        
        // 创建带子目录的项目结构
        let ui_dir = temp_dir.path().join("ui");
        let widgets_dir = temp_dir.path().join("widgets");
        let resources_dir = temp_dir.path().join("resources");
        fs::create_dir_all(&ui_dir).unwrap();
        fs::create_dir_all(&widgets_dir).unwrap();
        fs::create_dir_all(&resources_dir).unwrap();
        
        // 创建测试文件
        fs::write(ui_dir.join("MainWindow.ui"), "").unwrap();
        fs::write(widgets_dir.join("CustomButton.h"), "").unwrap();
        fs::write(resources_dir.join("icons.qrc"), "").unwrap();
        
        fs::write(&vcxproj_path, create_qt_vcxproj_complex()).unwrap();
        
        let parser = VsParser::new();
        let solution = parser.parse(&vcxproj_path).unwrap();
        let project = &solution.projects[0];
        
        let debug_config = project.configurations.get(&crate::core::BuildConfiguration::Debug).unwrap();
        
        // 验证路径解析
        let ui_paths: Vec<String> = debug_config.qt_settings.ui_files
            .iter()
            .map(|p| p.to_string_lossy().to_string())
            .collect();
        assert!(ui_paths.iter().any(|p| p.contains("ui\\MainWindow.ui") || p.contains("ui/MainWindow.ui")));
        
        let moc_paths: Vec<String> = debug_config.qt_settings.moc_files
            .iter()
            .map(|p| p.to_string_lossy().to_string())
            .collect();
        assert!(moc_paths.iter().any(|p| p.contains("widgets\\CustomButton.h") || p.contains("widgets/CustomButton.h")));
        
        let resource_paths: Vec<String> = debug_config.qt_settings.resource_files
            .iter()
            .map(|p| p.to_string_lossy().to_string())
            .collect();
        assert!(resource_paths.iter().any(|p| p.contains("resources\\icons.qrc") || p.contains("resources/icons.qrc")));
    }

    #[test]
    fn test_non_qt_project_handling() {
        use crate::parsers::{Parser, vs_parser::VsParser};

        let temp_dir = TempDir::new().unwrap();
        let vcxproj_path = temp_dir.path().join("NonQtProject.vcxproj");

        // 创建非 Qt 项目文件（普通的 C++ 项目）
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();

        let parser = VsParser::new();
        let solution = parser.parse(&vcxproj_path).unwrap();
        let project = &solution.projects[0];

        // 验证非 Qt 项目没有 Qt 设置
        for (_, config) in &project.configurations {
            assert!(!config.qt_settings.enabled);
            assert!(config.qt_settings.version.is_none());
            assert!(config.qt_settings.modules.is_empty());
            assert!(config.qt_settings.moc_files.is_empty());
            assert!(config.qt_settings.ui_files.is_empty());
            assert!(config.qt_settings.resource_files.is_empty());
        }
    }

    // ============== 层级化生成测试 ==============

    #[test]
    fn test_hierarchical_xmake_generation_in_root() {
        // 测试 vcxproj 在项目根目录时，只生成一个 xmake.lua
        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();
        let vcxproj_path = project_root.join("TestProject.vcxproj");

        // 创建测试项目文件
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();

        // 转换
        let converter = Converter::new();
        let config = Config::default();
        let result = converter.convert(&vcxproj_path, "xmake", project_root, &config);
        assert!(result.is_ok(), "Conversion should succeed: {:?}", result);

        // 验证只在根目录生成了 xmake.lua
        let root_xmake = project_root.join("xmake.lua");
        assert!(root_xmake.exists(), "Root xmake.lua should exist");

        // 验证生成的内容包含 target 定义
        let content = fs::read_to_string(&root_xmake).unwrap();
        assert!(content.contains("target(\"TestProject\")"));
        assert!(content.contains("set_kind(\"binary\")"));
        assert!(!content.contains("includes("), "Should not use includes when vcxproj is in root");
    }

    #[test]
    fn test_hierarchical_xmake_generation_in_subdirectory() {
        // 测试 vcxproj 在子目录时，生成层级化的 xmake.lua
        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();
        let project_dir = project_root.join("project");
        fs::create_dir_all(&project_dir).unwrap();

        let vcxproj_path = project_dir.join("TestProject.vcxproj");

        // 创建测试项目文件
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();

        // 转换
        let converter = Converter::new();
        let config = Config::default();
        let result = converter.convert(&vcxproj_path, "xmake", project_root, &config);
        assert!(result.is_ok(), "Conversion should succeed: {:?}", result);

        // 验证主 xmake.lua 存在
        let root_xmake = project_root.join("xmake.lua");
        assert!(root_xmake.exists(), "Root xmake.lua should exist");

        // 验证子 xmake.lua 存在
        let sub_xmake = project_dir.join("xmake.lua");
        assert!(sub_xmake.exists(), "Sub xmake.lua should exist");

        // 验证主 xmake.lua 包含 includes 指令
        let root_content = fs::read_to_string(&root_xmake).unwrap();
        assert!(root_content.contains("includes(\"project\")"), "Root should include subdirectory");
        assert!(root_content.contains("set_xmakever"));
        assert!(root_content.contains("add_rules(\"mode.debug\", \"mode.release\")"));

        // 验证子 xmake.lua 包含 target 定义
        let sub_content = fs::read_to_string(&sub_xmake).unwrap();
        assert!(sub_content.contains("target(\"TestProject\")"));
        assert!(sub_content.contains("set_kind(\"binary\")"));
        assert!(sub_content.contains("main.cpp"));
    }

    #[test]
    fn test_hierarchical_xmake_with_nested_source_paths() {
        // 测试当源文件在不同目录时，路径是否正确
        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();
        let project_dir = project_root.join("build");
        let src_dir = project_root.join("src");

        fs::create_dir_all(&project_dir).unwrap();
        fs::create_dir_all(&src_dir).unwrap();

        let vcxproj_path = project_dir.join("TestProject.vcxproj");

        // 创建测试项目文件，使用相对路径引用源文件
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();

        // 转换
        let converter = Converter::new();
        let config = Config::default();
        let result = converter.convert(&vcxproj_path, "xmake", project_root, &config);
        assert!(result.is_ok(), "Conversion should succeed");

        // 验证两个 xmake.lua 都存在
        assert!(project_root.join("xmake.lua").exists());
        assert!(project_dir.join("xmake.lua").exists());
    }

    #[test]
    fn test_relative_path_input() {
        use crate::parsers::{Parser, vs_parser::VsParser};

        let _lock = WORKDIR_LOCK.get_or_init(|| Mutex::new(())).lock().unwrap();
        // 测试使用相对路径作为输入
        let temp_dir = TempDir::new().unwrap();
        let project_dir = temp_dir.path().join("project");
        fs::create_dir_all(&project_dir).unwrap();

        let vcxproj_path = project_dir.join("TestProject.vcxproj");
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();

        // 改变当前工作目录到临时目录
        let original_dir = std::env::current_dir().unwrap();
        std::env::set_current_dir(temp_dir.path()).unwrap();

        // 使用相对路径解析
        let parser = VsParser::new();
        let relative_path = PathBuf::from("project").join("TestProject.vcxproj");
        let result = parser.parse(&relative_path);

        // 恢复原工作目录
        std::env::set_current_dir(&original_dir).unwrap();

        assert!(result.is_ok(), "Should parse with relative path: {:?}", result);

        let solution = result.unwrap();
        // source_directory 应该是绝对路径
        assert!(solution.source_directory.is_some());
        let source_dir = solution.source_directory.unwrap();
        assert!(source_dir.is_absolute(), "Source directory should be absolute path");
    }

    #[test]
    fn test_relative_path_conversion() {
        // 测试使用相对路径进行完整转换
        let _lock = WORKDIR_LOCK.get_or_init(|| Mutex::new(())).lock().unwrap();
        let temp_dir = TempDir::new().unwrap();
        let project_dir = temp_dir.path().join("project");
        fs::create_dir_all(&project_dir).unwrap();

        let vcxproj_path = project_dir.join("TestProject.vcxproj");
        fs::write(&vcxproj_path, create_test_vcxproj()).unwrap();

        // 改变当前工作目录
        let original_dir = std::env::current_dir().unwrap();
        std::env::set_current_dir(temp_dir.path()).unwrap();

        // 使用相对路径进行转换
        let converter = Converter::new();
        let config = Config::default();
        let relative_input = PathBuf::from("project").join("TestProject.vcxproj");
        // 注意：project_root 需要使用当前工作目录（因为已经 cd 过了）
        let current_dir = std::env::current_dir().unwrap();
        let result = converter.convert(&relative_input, "xmake", &current_dir, &config);

        // 恢复原工作目录
        std::env::set_current_dir(&original_dir).unwrap();

        assert!(result.is_ok(), "Conversion with relative path should succeed: {:?}", result);

        // 验证生成的文件
        let root_xmake = temp_dir.path().join("xmake.lua");
        let sub_xmake = project_dir.join("xmake.lua");

        if !root_xmake.exists() {
            eprintln!("Root xmake.lua not found at: {}", root_xmake.display());
        }
        if !sub_xmake.exists() {
            eprintln!("Sub xmake.lua not found at: {}", sub_xmake.display());
            eprintln!("Files in temp_dir:");
            if let Ok(entries) = fs::read_dir(temp_dir.path()) {
                for entry in entries {
                    if let Ok(entry) = entry {
                        eprintln!("  - {}", entry.path().display());
                    }
                }
            }
            eprintln!("Files in project_dir:");
            if let Ok(entries) = fs::read_dir(&project_dir) {
                for entry in entries {
                    if let Ok(entry) = entry {
                        eprintln!("  - {}", entry.path().display());
                    }
                }
            }
        }

        assert!(root_xmake.exists(), "Root xmake.lua should exist");
        assert!(sub_xmake.exists(), "Sub xmake.lua should exist");
    }
}
